|
ARD2
RC2
Airbag Reference Demonstrator using MPC5604P
|
00001 00017 #include "derivative.h" 00018 #include "Compile_Options.h" 00019 #include "MailDelivery.h" 00020 #include "eDMA.h" 00021 #include "DSPI.h" 00022 /* 00023 ****************************************************************************** 00024 * Constants 00025 ****************************************************************************** 00026 */ 00027 00028 /* 00029 ****************************************************************************** 00030 * Globals 00031 ****************************************************************************** 00032 */ 00034 vuint32_t gau32DSPIOutbox[(OUTBOX_MAX_BUFFER_CNT + 1u) * 2u]; 00036 TCD_t gatDSPIInbox[INBOX_MAX_BUFFER_CNT * 2u]; /* Today this is 4K */ 00038 vuint8_t gu8MailboxActiveOutboxOffset; 00040 vint8_t gi8MailboxActiveInboxOffset; 00042 vuint8_t gu8InboxDMA; 00044 vuint8_t gu8InactiveInboxDMA; 00046 vuint8_t gu8OutboxDMA; 00048 vuint8_t gu8InactiveOutboxDMA; 00049 /* 00050 ****************************************************************************** 00051 * u8fnMailDeliveryOfOutboxInit 00052 ****************************************************************************** 00053 */ 00054 uint8_t u8fnMailDeliveryOfOutboxInit(uint32_t* pu32Outbox, 00055 uint32_t* pu32Output, uint8_t u8DMAChannel) 00056 { 00057 TCD_t tMyDefaultConfig; 00058 00059 /* Outbox always has the size in its first address. Compensate for this */ 00060 tMyDefaultConfig.P.SADDR = ((uint32_t)pu32Outbox + 4u); 00061 /* Destination address is our output vehicle (DSPI, for example) */ 00062 tMyDefaultConfig.P.DADDR = (uint32_t)pu32Output; 00063 /* Modulus is 0 */ 00064 tMyDefaultConfig.P.SMOD = CLEAR; 00065 tMyDefaultConfig.P.DMOD = CLEAR; 00066 /* We will transfer 32-bit words */ 00067 tMyDefaultConfig.P.SSIZE = DMA_SIZE_32_BIT; 00068 tMyDefaultConfig.P.DSIZE = DMA_SIZE_32_BIT; 00069 tMyDefaultConfig.P.SOFF = 4u; /* Offset per minor loop (in bytes) */ 00070 tMyDefaultConfig.P.DOFF = 0u; /* Destination offset per minor loop */ 00071 tMyDefaultConfig.P.NBYTES = 4u; /* Inner loop transfer count (in bytes) */ 00072 tMyDefaultConfig.P.SLAST = CLEAR; 00073 tMyDefaultConfig.P.CITERE_LINK = CLEAR; 00074 tMyDefaultConfig.P.BITERE_LINK = CLEAR; 00075 tMyDefaultConfig.P.CITER = 0u; /* Times we'll execute our minor loop */ 00076 tMyDefaultConfig.P.BITER = 0u; /* Memory for the loop */ 00077 tMyDefaultConfig.P.D_REQ = TRUE; /* Clear HW Start requests after major loop is done */ 00078 00079 tMyDefaultConfig.P.DLAST_SGA = CLEAR; /* Last destination offset */ 00080 tMyDefaultConfig.P.MAJORLINKCH = CLEAR; 00081 tMyDefaultConfig.P.BWC = DMA_BWC_4_CYCLE_STALL; 00082 tMyDefaultConfig.P.MAJORE_LINK = CLEAR; /* Disable ch2ch linking */ 00083 tMyDefaultConfig.P.E_SG = CLEAR; 00084 00085 /* EDMA's DONE bit must be set to take the interrupt. This will be */ 00086 /* updated as necessary, but for now, set it. */ 00087 tMyDefaultConfig.P.DONE = TRUE; 00088 00089 tMyDefaultConfig.P.INT_HALF = CLEAR; 00090 tMyDefaultConfig.P.INT_MAJ = CLEAR; /* No ISR for Outbox done */ 00091 tMyDefaultConfig.P.START = CLEAR; 00092 00093 vfnDMAConfig(&tMyDefaultConfig, u8DMAChannel); 00094 00095 /* Config DMAMux to go along with it */ 00096 vfnDMAMUXInit(u8DMAChannel, DMA_SOURCE_DSPI0_TX, CLEAR, TRUE); 00097 00098 /* Remember which is the initial DMA we're using */ 00099 gu8OutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH; 00100 gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH; 00101 00102 return (CLEAR); 00103 } 00104 /* 00105 ****************************************************************************** 00106 * u8fnMailDeliveryToInboxInit 00107 ****************************************************************************** 00108 */ 00109 uint8_t u8fnMailDeliveryToInboxInit(uint16_t* pu16Input) 00110 { 00111 uint8_t u8Counter; 00112 TCD_t tMyDefaultConfig; 00113 00114 00115 tMyDefaultConfig.P.SADDR = (uint32_t)pu16Input; 00116 tMyDefaultConfig.P.DADDR = (uint32_t)CLEAR; 00117 tMyDefaultConfig.P.SMOD = CLEAR; 00118 tMyDefaultConfig.P.DMOD = CLEAR; 00119 tMyDefaultConfig.P.SSIZE = DMA_SIZE_16_BIT; 00120 tMyDefaultConfig.P.DSIZE = DMA_SIZE_16_BIT; 00121 tMyDefaultConfig.P.SOFF = 0u; /* Offset per minor loop (in bytes) */ 00122 tMyDefaultConfig.P.DOFF = 2u; /* Destination offset per minor loop */ 00123 tMyDefaultConfig.P.NBYTES = 2u; /* Inner loop transfer count (in bytes) */ 00124 tMyDefaultConfig.P.SLAST = CLEAR; 00125 tMyDefaultConfig.P.CITERE_LINK = CLEAR; 00126 tMyDefaultConfig.P.BITERE_LINK = CLEAR; 00127 tMyDefaultConfig.P.CITER = 0u; /* Times we'll execute our minor loop */ 00128 tMyDefaultConfig.P.BITER = 0u; /* Memory for the loop */ 00129 00130 tMyDefaultConfig.P.DLAST_SGA = CLEAR; /* By default, zero. This will change with lnking */ 00131 tMyDefaultConfig.P.MAJORLINKCH = MAILDELIVERY_INBOX1_DMA_CH; 00132 tMyDefaultConfig.P.BWC = DMA_BWC_4_CYCLE_STALL; 00133 tMyDefaultConfig.P.MAJORE_LINK = CLEAR; /* Disable ch2ch linking */ 00134 tMyDefaultConfig.P.E_SG = CLEAR; 00135 tMyDefaultConfig.P.D_REQ = CLEAR; /* Will be modified as the stack grows */ 00136 tMyDefaultConfig.P.INT_HALF = CLEAR; 00137 tMyDefaultConfig.P.INT_MAJ = CLEAR; /* Isr will be added as the stack grows */ 00138 tMyDefaultConfig.P.DONE = CLEAR; 00139 tMyDefaultConfig.P.ACTIVE = CLEAR; 00140 tMyDefaultConfig.P.START = CLEAR; 00141 00142 /* Copy values to predetermined INBOXes */ 00143 vfnDMAConfig(&tMyDefaultConfig, MAILDELIVERY_INBOX1_DMA_CH); 00144 00145 /* Configure all other inbox pointers associated to this one */ 00146 for(u8Counter = MAILDELIVERY_INBOX1_DMA_INDEX_START; u8Counter 00147 <= MAILDELIVERY_INBOX1_DMA_INDEX_END; u8Counter++) 00148 { 00149 gatDSPIInbox[u8Counter] = tMyDefaultConfig; 00150 } 00151 00152 /* Small mods for the second inbox family */ 00153 tMyDefaultConfig.P.MAJORLINKCH = MAILDELIVERY_INBOX2_DMA_CH; 00154 00155 /* Copy values to predetermined INBOXes */ 00156 vfnDMAConfig(&tMyDefaultConfig, MAILDELIVERY_INBOX2_DMA_CH); 00157 for(u8Counter = MAILDELIVERY_INBOX2_DMA_INDEX_START; u8Counter 00158 <= MAILDELIVERY_INBOX2_DMA_INDEX_END; u8Counter++) 00159 { 00160 gatDSPIInbox[u8Counter] = tMyDefaultConfig; 00161 } 00162 00163 /* Remember which DMA we're using */ 00164 gu8InboxDMA = MAILDELIVERY_INBOX1_DMA_CH; 00165 gu8InactiveInboxDMA = MAILDELIVERY_INBOX2_DMA_CH; 00166 00167 /* Config DMAMux to go along with it */ 00168 vfnDMAMUXInit(gu8InboxDMA, DMA_SOURCE_DSPI0_RX, CLEAR, TRUE); 00169 00170 return (CLEAR); 00171 } 00172 /* 00173 ****************************************************************************** 00174 * vfnMailboxInit 00175 ****************************************************************************** 00176 */ 00177 void vfnMailboxInit(void) 00178 { 00179 /* Start by initializing outboxes */ 00180 /* Erase count - contents is not relevant as it will be overwritten */ 00181 gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_1] = CLEAR; 00182 gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_2] = CLEAR; 00183 00184 /* First active Mailbox is the first half */ 00185 gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_1; 00186 gi8MailboxActiveInboxOffset = MAILBOX_ACTIVE_INBOX_IS_1; 00187 00188 return; 00189 } 00190 00191 /* 00192 ****************************************************************************** 00193 * u8fnMailboxAppendToInbox 00194 ****************************************************************************** 00195 */ 00196 uint8_t u8fnMailboxAppendToInbox(const uint16_t* pu16MsgResponse, 00197 uint16_t u16Size) 00198 { 00199 TCD_t* ptCurrentTCD; 00200 TCD_t* ptPreviousTCD; 00201 00202 /* We need to find which registers we're modifying */ 00203 if(MAILBOX_ACTIVE_INBOX_IS_1 == gi8MailboxActiveInboxOffset) 00204 { 00205 /* Modifying directly the DMA, no previous channel, start count for */ 00206 /* gi8MailboxActiveInboxOffset. */ 00207 ptCurrentTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX1_DMA_CH]); 00208 ptPreviousTCD = (TCD_t*)MAILBOX_NO_PREVIOUS_INBOX; 00209 gi8MailboxActiveInboxOffset = MAILDELIVERY_INBOX1_DMA_INDEX_START; 00210 } 00211 else if(MAILBOX_ACTIVE_INBOX_IS_2 == gi8MailboxActiveInboxOffset) 00212 { 00213 /* Modifying directly the DMA, no previous channel, start count for */ 00214 /* gi8MailboxActiveInboxOffset. */ 00215 ptCurrentTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX2_DMA_CH]); 00216 ptPreviousTCD = (TCD_t*)MAILBOX_NO_PREVIOUS_INBOX; 00217 gi8MailboxActiveInboxOffset = MAILDELIVERY_INBOX2_DMA_INDEX_START; 00218 } 00219 else 00220 { 00221 /* Modifying some location in RAM, and previous channel may come from */ 00222 /* different sources. */ 00223 ptCurrentTCD = &gatDSPIInbox[gi8MailboxActiveInboxOffset]; 00224 if(MAILDELIVERY_INBOX1_DMA_INDEX_START == gi8MailboxActiveInboxOffset) 00225 { 00226 /* Previous value was in the DMA itself */ 00227 ptPreviousTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX1_DMA_CH]); 00228 } 00229 else if(MAILDELIVERY_INBOX2_DMA_INDEX_START == gi8MailboxActiveInboxOffset) 00230 { 00231 /* Previous value was in the DMA itself */ 00232 ptPreviousTCD = (TCD_t*)&(EDMA.TCD[MAILDELIVERY_INBOX2_DMA_CH]); 00233 } 00234 else 00235 { 00236 /* Previous channel was already in RAM */ 00237 ptPreviousTCD = &gatDSPIInbox[gi8MailboxActiveInboxOffset - 1u]; 00238 } 00239 /* Increment buffer count */ 00240 gi8MailboxActiveInboxOffset++; 00241 } 00242 /* Start by modifying this TCD's number of Major cycles according to u16Size */ 00243 ptCurrentTCD->P.CITER = u16Size; 00244 ptCurrentTCD->P.BITER = u16Size; 00245 00246 /* Link to the pointer */ 00247 ptCurrentTCD->P.DADDR = (uint32_t)pu16MsgResponse; 00248 00249 /* Call the interrupt for when we're done */ 00250 ptCurrentTCD->P.INT_MAJ = TRUE; 00251 00252 /* Clear any existing "DONE" flags */ 00253 ptCurrentTCD->P.DONE = CLEAR; 00254 00255 /* Clear any existing links to load new config after transfer */ 00256 ptCurrentTCD->P.DLAST_SGA = CLEAR; 00257 00258 /* Disable loading any extra registers after this */ 00259 ptCurrentTCD->P.E_SG = CLEAR; 00260 00261 /* Continue only if we're not writing to the original inbox */ 00262 if(MAILBOX_NO_PREVIOUS_INBOX != ptPreviousTCD) 00263 { 00264 /* Disable the Isr for the previous CH */ 00265 ptPreviousTCD->P.INT_MAJ = CLEAR; 00266 00267 /* Enable loading of this info */ 00268 ptPreviousTCD->P.E_SG = TRUE; 00269 00270 /* Make sure that the next register is loaded */ 00271 ptPreviousTCD->P.DLAST_SGA = (int32_t)(ptCurrentTCD); 00272 } 00273 else 00274 { 00275 /* Nothing I think... */ 00276 } 00277 00278 return (CLEAR); 00279 } 00280 /* 00281 ****************************************************************************** 00282 * u8fnMailboxAppendToDSPIOutbox 00283 ****************************************************************************** 00284 */ 00285 uint8_t u8fnMailboxAppendToDSPIOutbox(uint8_t u8DSPIInstance, uint8_t u8CS, 00286 uint8_t u8ContCS, 00287 uint8_t u8EndOfQueueFlag, 00288 uint16_t* pu16Msg, uint16_t u16Size) 00289 { 00290 /* Locals */ 00291 uint8_t u8Status; 00292 uint32_t u32Message; 00293 u8Status = CLEAR; 00294 00295 /* Pre-calculate Message */ 00296 /* Format as PUSHR for DSPI transfers */ 00297 u32Message = FORMAT_PUSHR(u8DSPIInstance, 00298 u8CS, 00299 u8ContCS, 00300 u8EndOfQueueFlag, 00301 CLEAR); 00302 00303 for(; CLEAR < u16Size; u16Size--) 00304 { 00305 /* Append to outbox */ 00306 u8Status |= u8fnMailboxAppendToOutbox( 00307 (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]), 00308 u32Message | *pu16Msg); 00309 /* Increment pointer to next value */ 00310 pu16Msg++; 00311 } 00312 00313 return (u8Status); 00314 } 00315 /* 00316 ****************************************************************************** 00317 * u8fnMailboxAppendToDSPIOutbox 00318 ****************************************************************************** 00319 */ 00320 uint8_t u8fnMailboxAppendToCompositeDSPIOutbox(uint8_t u8DSPIInstance1, 00321 uint8_t u8DSPIInstance2, 00322 uint8_t u8CS, 00323 uint16_t* pu16Msg1, 00324 uint16_t* pu16Msg2, 00325 uint16_t u16SizeAtOrigin) 00326 { 00327 /* Locals */ 00328 uint8_t u8Status; 00329 uint32_t u32Message1; 00330 uint32_t u32Message2; 00331 u8Status = CLEAR; 00332 00333 /* Pre-calculate PUSHR */ 00334 u32Message1 = FORMAT_PUSHR(u8DSPIInstance1, u8CS, TRUE, CLEAR, CLEAR); 00335 u32Message2 = FORMAT_PUSHR(u8DSPIInstance2, u8CS, CLEAR, CLEAR, CLEAR); 00336 00337 for(; CLEAR < u16SizeAtOrigin; u16SizeAtOrigin--) 00338 { 00339 /* Append to outbox */ 00340 u8Status |= u8fnMailboxAppendToOutbox( 00341 (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]), 00342 u32Message1 | *pu16Msg1); 00343 /* Redo for Msg 2 */ 00344 u8Status |= u8fnMailboxAppendToOutbox( 00345 (uint32_t*)(&gau32DSPIOutbox[gu8MailboxActiveOutboxOffset]), 00346 u32Message2 | *pu16Msg2); 00347 /* Increment pointer to next value */ 00348 pu16Msg1++; 00349 pu16Msg2++; 00350 } 00351 00352 return (u8Status); 00353 } 00354 /* 00355 ****************************************************************************** 00356 * u8fnAppendToOutbox 00357 ****************************************************************************** 00358 */ 00359 uint8_t u8fnMailboxAppendToOutbox(uint32_t* pu32Mailbox, uint32_t u32Message) 00360 { 00361 /* Locals */ 00362 uint8_t u8Status; 00363 00364 /* Init locals */ 00365 u8Status = CLEAR; 00366 00367 if(OUTBOX_MAX_BUFFER_CNT > *pu32Mailbox) 00368 { 00369 (*pu32Mailbox)++; 00370 *(pu32Mailbox + *pu32Mailbox) = u32Message; 00371 00372 /* increment pointers in outbox DMAs */ 00373 /* Subtract equivalent values to when the major loop is done */ 00374 /* CTAR will be copied to just before data is sent, and therefore is not */ 00375 /* tinkered-with here. */ 00376 EDMA.TCD[gu8OutboxDMA].BITER++; 00377 EDMA.TCD[gu8OutboxDMA].SLAST -= (4u); 00378 } 00379 else 00380 { 00381 u8Status = MAILBOX_CAPACITY_HAS_BEEN_REACHED; 00382 } 00383 return (u8Status); 00384 } 00385 00386 /* 00387 ****************************************************************************** 00388 * vfnMailDeliveryTriggerOutbox 00389 ****************************************************************************** 00390 */ 00391 void vfnMailDeliveryTriggerOutbox(uint8_t u8DMAMuxChannel, uint8_t u8Enable) 00392 { 00393 /* Copy BITER to CITER */ 00394 EDMA.TCD[u8DMAMuxChannel].CITER = EDMA.TCD[u8DMAMuxChannel].BITER; 00395 00396 /* Clear DONE flag */ 00397 EDMA.TCD[u8DMAMuxChannel].DONE = CLEAR; 00398 00399 /* Connect Proper EDMA HW Outbox triggers */ 00400 EDMA.SERQR.R = u8DMAMuxChannel; 00401 00402 vfnDMAMUXInit(u8DMAMuxChannel, DMA_SOURCE_DSPI0_TX, CLEAR, u8Enable); 00403 00404 return; 00405 } 00406 00407 /* 00408 ****************************************************************************** 00409 * vfnMailboxSwitchActiveMailboxes 00410 ****************************************************************************** 00411 */ 00412 void vfnMailboxSwitchActiveMailboxes(void) 00413 { 00414 /* This routine shall be called when we want to switch the target outbox */ 00415 /* to which code will be writing to. As such, it will also switch the */ 00416 /* active DMA channel associated with a given outbox. */ 00417 00418 if(MAILDELIVERY_OUTBOX1_DMA_CH == gu8OutboxDMA) 00419 { 00420 /* We're switchting to the second outbox. Clear its count. */ 00421 gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_2; 00422 gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_2] = CLEAR; 00423 gi8MailboxActiveInboxOffset = MAILBOX_ACTIVE_INBOX_IS_2; 00424 00425 gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH; 00426 gu8OutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH; 00427 gu8InactiveInboxDMA = MAILDELIVERY_INBOX1_DMA_CH; 00428 gu8InboxDMA = MAILDELIVERY_INBOX2_DMA_CH; 00429 } 00430 else 00431 { 00432 /* We're switching to the first outbox. Clear it's count */ 00433 gu8MailboxActiveOutboxOffset = OUTBOX_ACTIVE_OUTBOX_IS_1; 00434 gau32DSPIOutbox[OUTBOX_ACTIVE_OUTBOX_IS_1] = CLEAR; 00435 gi8MailboxActiveInboxOffset = MAILBOX_ACTIVE_INBOX_IS_1; 00436 00437 gu8InactiveOutboxDMA = MAILDELIVERY_OUTBOX2_DMA_CH; 00438 gu8OutboxDMA = MAILDELIVERY_OUTBOX1_DMA_CH; 00439 gu8InactiveInboxDMA = MAILDELIVERY_INBOX2_DMA_CH; 00440 gu8InboxDMA = MAILDELIVERY_INBOX1_DMA_CH; 00441 } 00442 00443 /* Reset count before writing anything for output */ 00444 EDMA.TCD[gu8OutboxDMA].SLAST = CLEAR; 00445 00446 return; 00447 } 00448 /* 00449 ****************************************************************************** 00450 * 00451 * End of file. 00452 * 00453 ****************************************************************************** 00454 */